package ejb.com.bbva.cbm.util;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.log4j.Logger;

import ejb.cbm.admin.entity.CentroCostoProtegidoEntity;
import ejb.cbm.admin.entity.ParametroEntity;
import ejb.cbm.admin.entity.TipoParametroEntity;
import ejb.cbm.admin.entity.TransaccionEntity;
import ejb.cbm.seguridad.bean.PerfilBean;
import ejb.com.bbva.cbm.dominio.DenominacionEntity;
import ejb.com.bbva.cbm.dominio.TransaccionSignificativaEntity;

public class CacheDatos implements Serializable {
	private static final long serialVersionUID = 128103192837231743L;

	static Logger logger = Logger.getLogger(CacheDatos.class.getName());

	private static CacheDatos instancia;
	
	private boolean sistemaActivado;

	private double itf;
	private double paramValCheque;

	private List<TipoParametroEntity> tiposParametro;
	private List<ParametroEntity> divisas;
	private List<ParametroEntity> tiposDocumento;
	private List<ParametroEntity> tiposTarjeta;
	private List<ParametroEntity> estadosConfirmacionIngreso;
	private List<ParametroEntity> estadosRegistro;
	private List<ParametroEntity> estadosEnvioHost;
	private List<ParametroEntity> segmentosCliente;
	private List<ParametroEntity> tiposCheque;
	private List<ParametroEntity> tiposCaja;
	private List<ParametroEntity> tiposDenominacion;
	private List<ParametroEntity> estadosCaja;
	private List<ParametroEntity> estadosOficina;
	private List<ParametroEntity> motivoscancelacion;
	

	private List<DenominacionEntity> denominaciones;
	private List<TransaccionEntity> configuracionTransacciones;
	private List<TransaccionEntity> transaccionesHabilitadas;
	private List<TransaccionEntity> transaccionesExtorno;
	private List<TransaccionEntity> transaccionesOperacion;
	private List<TransaccionEntity> transaccionesTodas;
	private List<TransaccionEntity> transaccionesAuditoria;
	private List<TransaccionEntity> transaccionesEfectivoCheque;
	private List<TransaccionSignificativaEntity> transaccionesSignificativa;
	
	private List<CentroCostoProtegidoEntity> centroCostoProtegido;
	private List<ParametroEntity> divisaTarjeta;
	private TransaccionSignificativaEntity transaccionSignificativaDolares;
	
	private List<PerfilBean> perfiles;
	
	Map<String, Object> mapacache = null;
	
	public Map<String, Object> getMapacache() {
		return mapacache;
	}

	public void setMapacache(Map<String, Object> mapacache) {
		this.mapacache = mapacache;
	}

	private CacheDatos() {
		mapacache = new HashMap<String, Object>();
	}
	
	public CacheDatos getInstancia(){
		return getInstance();
	}
	
	public static CacheDatos getInstance() {
		
		if(instancia == null) {
			instancia = new CacheDatos();			 
		}
		
		return instancia;
	}
	
	public static CacheDatos saveCache() {
		try {
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return instancia;
	}
	
	public Map<Long, ParametroEntity> getMapaParametrosPorTipoParametro(String codigoUnico){
		if(!mapacache.containsKey(codigoUnico))
			return null;
		else
			return (Map<Long, ParametroEntity>)mapacache.get(codigoUnico);
	}
	
	@SuppressWarnings("unchecked")
	public void cargarDatosPametrosCache(List<TipoParametroEntity> tipoParametros) {		
		//Map<Long, TipoParametroEntity> mapacachelvl2 = new HashMap<Long, TipoParametroEntity>();
		
		for (TipoParametroEntity tipoParametroEntity : tipoParametros) {
			if(!mapacache.containsKey(tipoParametroEntity.getCodigounico())){
				mapacache.put(tipoParametroEntity.getCodigounico(), new HashMap<Long, ParametroEntity>());
			}
			for(ParametroEntity parametroEntity : tipoParametroEntity.getParametros()){
				/*if(tipoParametroEntity.getCodigotipoparametro() == Constante.TIPO_DOCUMENTOS_ID){
					if(parametroEntity.getParametroPadre() == null) {
						((Map<Long, ParametroEntity>)mapacache.get(tipoParametroEntity.getCodigounico())).put(parametroEntity.getValornumerico().longValue(), parametroEntity);
					}
				}else{*/
					if(parametroEntity.getParametroPadre() == null) {
						((Map<Long, ParametroEntity>)mapacache.get(tipoParametroEntity.getCodigounico())).put(parametroEntity.getCodigoparametro(), parametroEntity);
					}
				//}
			}
			
			if(tipoParametroEntity.getCodigotipoparametro() == Constante.TIPO_DOCUMENTOS_ID){
				Map<Long, ParametroEntity> mapTemp = (Map<Long, ParametroEntity>)mapacache.get(tipoParametroEntity.getCodigounico());
				List list = new ArrayList(mapTemp.entrySet());
				Collections.sort(list, new Comparator() {
		             public int compare(Object o1, Object o2) {
			           return ((Comparable) ((Map.Entry) (o1)).getValue())
			           .compareTo(((Map.Entry) (o2)).getValue());
		             }
				});
				Map mapFinal = new HashMap();
				for (Iterator it = list.iterator(); it.hasNext();) {
				     Map.Entry entry = (Map.Entry)it.next();
				     mapFinal.put(entry.getKey(), entry.getValue());
				}
				
				mapacache.put(tipoParametroEntity.getCodigounico(), mapFinal);
			}
			
		}
		
		logger.info("Terminada la carga de Parametros: " + mapacache.toString());
		/*
		for (ParametroEntity parametroEntity : parametros) {
			
			mapacachelvl2.get(parametroEntity.get)
			parametroEntity.getCodigoparametro();
		}*/
	}
	public void actualizarParametroCache(ParametroEntity parametro) {
		HashMap<Long, ParametroEntity> parametros = (HashMap<Long, ParametroEntity>) mapacache.get(parametro.getTipoparametro().getCodigounico());
		parametros.put(parametro.getCodigoparametro(), parametro);
		if(Constante.TIPO_DIVISA_CU.equals(parametro.getTipoparametro().getCodigounico())) {
			
		}
	}
	public void eliminarParametroCache(ParametroEntity parametro) {
		HashMap<Long, ParametroEntity> parametros = (HashMap<Long, ParametroEntity>) mapacache.get(parametro.getTipoparametro().getCodigounico());
		parametros.remove(parametro.getCodigoparametro());
		mapacache.put(parametro.getTipoparametro().getCodigounico(), parametros);
	}
	//@Deprecated
	public void cargarDatosParametros(List<TipoParametroEntity> tiposParametro, List<ParametroEntity> parametros) {
		this.tiposParametro = tiposParametro;
		for (TipoParametroEntity tipoParametroEntity : tiposParametro) {
			cargarParametrosPorTipo(tipoParametroEntity.getCodigotipoparametro(), parametros);
		}
	}
	//@Deprecated
	private void cargarParametrosPorTipo(long tipoParametroId, List<ParametroEntity> parametrosTodos) {
		List<ParametroEntity> parametrosTipo = new ArrayList<ParametroEntity>();
		
		for (ParametroEntity parametroEntity : parametrosTodos) {
			if(parametroEntity.getTipoparametro().getCodigotipoparametro().longValue() == tipoParametroId) {
				parametrosTipo.add(parametroEntity);
			}
		}
			
		if(Constante.TIPO_DOCUMENTOS_ID == tipoParametroId) {
			tiposDocumento = parametrosTipo;
		} else if(Constante.TIPO_DIVISAS_ID == tipoParametroId) {
			divisas = parametrosTipo;
		} else if(Constante.TIPO_TARJETAS_ID == tipoParametroId) {
			tiposTarjeta = parametrosTipo;
		} else if(Constante.TIPO_ESTADOS_CONF_INGR_ID == tipoParametroId) {
			estadosConfirmacionIngreso = parametrosTipo; 
		} else if(Constante.TIPO_ESTADOS_REGISTRO_ID == tipoParametroId) {
			estadosRegistro = parametrosTipo;
		} else if(Constante.TIPO_ESTADOS_ENVIO_HOST_ID == tipoParametroId) {
			estadosEnvioHost = parametrosTipo;
		} else if(Constante.TIPO_SEGMENTOS_CLIENTE_ID == tipoParametroId) {
			segmentosCliente = parametrosTipo;
		} else if(Constante.TIPO_CHEQUES_ID == tipoParametroId) {
			tiposCheque = parametrosTipo;
		} else if(Constante.TIPO_CAJAS_ID == tipoParametroId) {
			tiposCaja = parametrosTipo;
		} else if(Constante.TIPO_MOTIVOCANCELACION_ID == tipoParametroId) {
			motivoscancelacion = parametrosTipo;
		} else if(Constante.TIPO_DENOMINACIONES_ID == tipoParametroId) {
			tiposDenominacion = parametrosTipo;
		} else if(Constante.TIPO_ESTADOS_CAJA_ID == tipoParametroId) {
			estadosCaja = parametrosTipo;
		}
	}
	
	public boolean isSistemaActivado() {
		return sistemaActivado;
	}

	public void setSistemaActivado(boolean sistemaActivado) {
		this.sistemaActivado = sistemaActivado;
	}

	public List<ParametroEntity> ordenarPorValorNumerico(List<ParametroEntity> lista) {
		List<ParametroEntity> ordenado = new ArrayList<ParametroEntity>();
		
		while(lista != null && lista.size() > 0) {
			ParametroEntity parametroEntity = lista.get(0);
			double minimo = (parametroEntity.getValornumerico()==null)?0:parametroEntity.getValornumerico();
			for (ParametroEntity parametroEntityAux : lista) {
				if(parametroEntityAux.getValornumerico() == null) {
					if (0 < minimo) {
						minimo = 0;
						parametroEntity = parametroEntityAux;
					}
				} else if(parametroEntityAux.getValornumerico().doubleValue() < minimo) {
					minimo = parametroEntityAux.getValornumerico().doubleValue();
					parametroEntity = parametroEntityAux;
				}
			}
			lista.remove(parametroEntity);
			ordenado.add(parametroEntity);
		}
		
		return ordenado;
	}
	
	public List<ParametroEntity> getDivisas() {
		return getListaParametrosMapa(Constante.TIPO_DIVISA_CU);
	}

	public void setDivisas(List<ParametroEntity> divisas) {
		this.divisas = divisas;
	}

	public List<ParametroEntity> getTiposDocumento() {
		return getListaParametrosMapa(Constante.TIPO_DOCUMENTO_IDENTIFICACION);
	}

	public void setTiposDocumento(List<ParametroEntity> tiposDocumento) {
		this.tiposDocumento = tiposDocumento;
	}

	public List<ParametroEntity> getTiposTarjeta() {
		return tiposTarjeta;
	}

	public void setTiposTarjeta(List<ParametroEntity> tiposTarjeta) {
		this.tiposTarjeta = tiposTarjeta;
	}

	public List<ParametroEntity> getEstadosConfirmacionIngreso() {
		return estadosConfirmacionIngreso;
	}

	public void setEstadosConfirmacionIngreso(
			List<ParametroEntity> estadosConfirmacionIngreso) {
		this.estadosConfirmacionIngreso = estadosConfirmacionIngreso;
	}

	public List<ParametroEntity> getEstadosRegistro() {
		return estadosRegistro;
	}

	public void setEstadosRegistro(List<ParametroEntity> estadosRegistro) {
		this.estadosRegistro = estadosRegistro;
	}

	public List<ParametroEntity> getEstadosEnvioHost() {
		return estadosEnvioHost;
	}

	public void setEstadosEnvioHost(List<ParametroEntity> estadosEnvioHost) {
		this.estadosEnvioHost = estadosEnvioHost;
	}

	public List<ParametroEntity> getTiposCheque() {
		return tiposCheque;
	}

	public void setTiposCheque(List<ParametroEntity> tiposCheque) {
		this.tiposCheque = tiposCheque;
	}

	public List<ParametroEntity> getTiposCaja() {
		return tiposCaja;
	}

	public void setTiposCaja(List<ParametroEntity> tiposCaja) {
		this.tiposCaja = tiposCaja;
	}

	public List<ParametroEntity> getEstadosCaja() {
		return estadosCaja;
	}

	public void setEstadosCaja(List<ParametroEntity> estadosCaja) {
		this.estadosCaja = estadosCaja;
	}

	public List<TransaccionEntity> getConfiguracionTransacciones() {
		return configuracionTransacciones;
	}

	public void setConfiguracionTransacciones(List<TransaccionEntity> configuracionTransacciones) {
		this.configuracionTransacciones = configuracionTransacciones;
		
		transaccionesHabilitadas = new ArrayList<TransaccionEntity>();
		
		if(configuracionTransacciones != null) {
			//Recorremos las transacciones
			for (TransaccionEntity transaccionEntity : configuracionTransacciones) {
				//Agregamos solo las transacciones habilitadas
				if(transaccionEntity.getFlaghabilitar() == 1 && transaccionEntity.getCodigotransaccion()!=2) {
					transaccionesHabilitadas.add(transaccionEntity);
				}
			}
		}
		/*
		transaccionesExtorno = new ArrayList<TransaccionEntity>();
		
		if(configuracionTransacciones.size() > 0) {
			//Recorremos las transacciones
			for (TransaccionEntity transaccionEntity : configuracionTransacciones) {
				//Agregamos solo las transacciones habilitadas
				if(transaccionEntity.getFlagExtorno()) {
					transaccionesExtorno.add(transaccionEntity);
				}
			}
		}*/
	}

	public void setTiposDenominacion(List<ParametroEntity> tiposDenominacion) {
		this.tiposDenominacion = tiposDenominacion;
	}

	public List<ParametroEntity> getTiposDenominacion() {
		return tiposDenominacion;
	}

	public void setSegmentosCliente(List<ParametroEntity> segmentosCliente) {
		this.segmentosCliente = segmentosCliente;
	}

	public List<ParametroEntity> getListaParametrosMapa(String codigoUnico) {
		List<ParametroEntity> lista = new ArrayList<ParametroEntity>();
		
		Map<Long, ParametroEntity> parametros = (HashMap<Long, ParametroEntity>) mapacache.get(codigoUnico);
		
		if(parametros != null) {
	    	for (Iterator<ParametroEntity> iterator = parametros.values().iterator(); iterator.hasNext();) {
	    		ParametroEntity parametro = (ParametroEntity) iterator.next();
	    		if (parametro.getParametroPadre() == null && parametro.getFlagactivo() == 1) {
		    		lista.add(parametro);
				} 
			}
		}
		return ordenarPorValorNumerico(lista);
	}
	public List<ParametroEntity> getSegmentosCliente() {
		return getListaParametrosMapa(Constante.TIPO_SEGMENTOS_CLIENTE_CU);
	}
	public List<ParametroEntity> getSimbolosDivisa() {
		return getListaParametrosMapa(Constante.TIPO_DIVISA_SIMBOLO_CU);
	}
	public String getSimboloDivisaPorId(String divisaId) {
		Map<Long, ParametroEntity> parametros = (Map<Long, ParametroEntity>) mapacache.get(Constante.TIPO_DIVISA_SIMBOLO_CU);
		
		if(parametros != null) {
	    	for (Iterator<ParametroEntity> iterator = parametros.values().iterator(); iterator.hasNext();) {
	    		ParametroEntity simbolo = iterator.next();
	    		if (divisaId.equals(simbolo.getValoralfanumerico())) {
					return simbolo.getDescripcion();
				}
			}
		}
		return "";
	}

	public void setDenominaciones(List<DenominacionEntity> denominaciones) {
		this.denominaciones = denominaciones;
	}

	public List<DenominacionEntity> getDenominaciones() {
		return denominaciones;
	}

	public void setTransaccionesHabilitadas(List<TransaccionEntity> transaccionesHabilitadas) {
		this.transaccionesHabilitadas = transaccionesHabilitadas;
	}

	public List<TransaccionEntity> getTransaccionesHabilitadas() {
		return transaccionesHabilitadas;
	}

	public void setMotivoscancelacion(List<ParametroEntity> motivoscancelacion) {
		this.motivoscancelacion = motivoscancelacion;
	}

	public List<ParametroEntity> getMotivoscancelacion() {
		return motivoscancelacion;
	}

	public void setItf(double itf) {
		this.itf = itf;
	}

	public double getItf() {
		Map<Long, ParametroEntity> mapItf = getMapaParametrosPorTipoParametro("ITF");
		if(mapItf != null) {
			for(ParametroEntity parametro :mapItf.values()){
				itf = parametro.getValornumerico();
				break;
			}
			return itf;
		} else {
			return 0;
		}
	}
	
	
	public void setParamValCheque(double paramValCheque) {
		this.paramValCheque = paramValCheque;
	}
	
	public double getParamValCheque(){
		Map<Long, ParametroEntity> map = getMapaParametrosPorTipoParametro("PARAMETRO_VAL_CHEQUE");
		if(map != null) {
			for(ParametroEntity parametro :map.values()){
				paramValCheque = parametro.getValornumerico();
				break;
			}
			return paramValCheque;
		} else {
			return 0;
		}
	}

	public List<TransaccionSignificativaEntity> getTransaccionesSignificativa() {
		return transaccionesSignificativa;
	}

	public void setTransaccionesSignificativa(List<TransaccionSignificativaEntity> transaccionesSignificativa) {
		this.transaccionesSignificativa = transaccionesSignificativa;
	}

	public void setTransaccionesExtorno(List<TransaccionEntity> transaccionesExtorno) {
		this.transaccionesExtorno = transaccionesExtorno;
	}

	public List<TransaccionEntity> getTransaccionesExtorno() {
		return transaccionesExtorno;
	}

	public void setTiposParametro(List<TipoParametroEntity> tiposParametro) {
		this.tiposParametro = tiposParametro;
	}

	public List<TipoParametroEntity> getTiposParametro() {
		return tiposParametro;
	}

	public List<PerfilBean> getPerfiles() {
		return perfiles;
	}

	public void setPerfiles(List<PerfilBean> perfiles) {
		this.perfiles = perfiles;
	}

	
	public TransaccionEntity getTransaccionPorId(long transaccionId) {
		for (TransaccionEntity transaccion : configuracionTransacciones) {
			if(transaccion.getCodigotransaccion().longValue() == transaccionId) {
				return transaccion;
			}
		}
		return null;
	}

	public void setTransaccionesAuditoria(List<TransaccionEntity> transaccionesAuditoria) {
		this.transaccionesAuditoria = transaccionesAuditoria;
	}

	public List<TransaccionEntity> getTransaccionesAuditoria() {
		return transaccionesAuditoria;
	}

	public void setTransaccionesTodas(List<TransaccionEntity> transaccionesTodas) {
		this.transaccionesTodas = transaccionesTodas;
	}

	public List<TransaccionEntity> getTransaccionesTodas() {
		return transaccionesTodas;
	}
	
	public TransaccionSignificativaEntity getTransaccionSignificativaDolares() {
		for(TransaccionSignificativaEntity trans : this.transaccionesSignificativa){
			if(trans.getDivisaId().equals(Constante.DIVISA_DOLARES_ID)){
				return trans;
			}
		}
		return new TransaccionSignificativaEntity();
	}
	
	public String getValorParametro(String tipoParametro, String campoFiltro, String valorFiltro, String campoRequerido) {
		Map<Long, ParametroEntity> parametros = (Map<Long, ParametroEntity>) mapacache.get(tipoParametro);
		
		if(parametros != null) {
	    	for (Iterator<ParametroEntity> iterator = parametros.values().iterator(); iterator.hasNext();) {
	    		ParametroEntity parametro = iterator.next();
	    		try {
		    		String valorFiltroEncontrado = BeanUtils.getProperty(parametro, campoFiltro);
		    		if(valorFiltroEncontrado != null && valorFiltroEncontrado.equals(valorFiltro)) {
		    			return BeanUtils.getProperty(parametro, campoRequerido);
		    		}
				} catch (Exception e) {
					
				}
			}
		}
		return "";
	}
	
	public String getDescripcionParametroPorId(String tipoParametro, String valorFiltro) {
		return getValorParametro(tipoParametro, "valoralfanumerico", valorFiltro, "descripcion");
	}

	public List<CentroCostoProtegidoEntity> getCentroCostoProtegido() {
		return centroCostoProtegido;
	}

	public void setCentroCostoProtegido(
			List<CentroCostoProtegidoEntity> centroCostoProtegido) {
		this.centroCostoProtegido = centroCostoProtegido;
	}

	public void setTransaccionesOperacion(List<TransaccionEntity> transaccionesOperacion) {
		this.transaccionesOperacion = transaccionesOperacion;
	}

	public List<TransaccionEntity> getTransaccionesOperacion() {
		return transaccionesOperacion;
	}

	public void setTransaccionesEfectivoCheque(
			List<TransaccionEntity> transaccionesEfectivoCheque) {
		this.transaccionesEfectivoCheque = transaccionesEfectivoCheque;
	}

	public List<TransaccionEntity> getTransaccionesEfectivoCheque() {
		return transaccionesEfectivoCheque;
	}

	public void setEstadosOficina(List<ParametroEntity> estadosOficina) {
		this.estadosOficina = estadosOficina;
	}

	public List<ParametroEntity> getEstadosOficina() {
		return estadosOficina;
	}

	public void setDivisaTarjeta(List<ParametroEntity> divisaTarjeta) {
		this.divisaTarjeta = divisaTarjeta;
	}
	
	public String getConfiguracionProperty(Long parametroId) {
		return getValorParametro("PARAMETROS PROPERTIES", "codigoparametro", ""+parametroId, "valoralfanumerico");
	}
}
